﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;

namespace DragonRescue3D
{
    /// <summary>
    /// Defines all the behaviour for all destructable blocks within the level
    /// </summary>
    public class DestructibleBlock : GridObject
    {
        GamePlayManager _gamePlayManager;
        public GameObject _popPrefab;
        public GameObject _scoreAdditionPrefab;

        //--------------------------------------------------------
        /// <summary>
        /// Store a reference to the gameplaymanager for use later on
        /// </summary>
        void Start()
        {
            _gamePlayManager = GameObject.FindObjectOfType(typeof(GamePlayManager)) as GamePlayManager;
        }

        //--------------------------------------------------------
        /// <summary>
        /// Make the game object react whenever the user clicks on it
        /// </summary>
        void OnMouseDown()
        {
            IList<DestructibleBlock> adjacentBlocks = FindAdjacentBlocks();

            // Do we have any neighbouring blocks that are the same colour?
            if (adjacentBlocks.Count > 0)
            {
                // Hide and destroy ourselves first so our neighbours can't see us
                HideAndDestroyBlock();

                foreach (DestructibleBlock block in adjacentBlocks)
                {
                    // Recursively destroy all matching neighbouring blocks
                    block.DestroyAdjacentBlocks();
                }

                // Now create a pop and increase the score
                CreatePopEffect();
                Instantiate(_scoreAdditionPrefab, transform.position, transform.rotation);
                // Let the gameplaymanager know we have removed some blocks
                _gamePlayManager.UpdateStatus();
            }
        }

        /// <summary>
        /// Lets the game play manager know that the game status needs to be checked if a rocket
        /// has hit us.  
        /// </summary>
        /// <param name="collision"></param>
        void OnCollisionEnter(Collision collision)
        {
            // If we have been hit then self-destruct and inform the game manager
            if (collision.gameObject.tag == "Rocket")
            {
                HideAndDestroyBlock();
                CreatePopEffect();
                _gamePlayManager.UpdateStatus();
            }
        }

        //--------------------------------------------------------
        /// <summary>
        /// Finds any neighbouring blocks of the same colour/type
        /// </summary>
        /// <returns>list containing the neighbours</returns>
        public IList<DestructibleBlock> FindAdjacentBlocks()
        {
            IList<DestructibleBlock> retBlocks = new List<DestructibleBlock>();
            float distance = 1.1f;
            Ray upRay = new Ray(transform.position, Vector3.up);
            RaycastHit[] upHits = Physics.RaycastAll(upRay, distance);
            Ray downRay = new Ray(transform.position, Vector3.down);
            RaycastHit[] downHits = Physics.RaycastAll(downRay, distance);
            Ray leftRay = new Ray(transform.position, Vector3.left);
            RaycastHit[] leftHits = Physics.RaycastAll(leftRay, distance);
            Ray rightRay = new Ray(transform.position, Vector3.right);
            RaycastHit[] rightHits = Physics.RaycastAll(rightRay, distance);

            // Test for blocks above us 
            foreach (RaycastHit hit in upHits)
            {
                // Have we hit an adjacent block of the same colour
                if (hit.transform.tag == transform.tag)
                {
                    retBlocks.Add(hit.transform.GetComponent<DestructibleBlock>());
                    break;
                }
            }

            // Test for blocks below us
            foreach (RaycastHit hit in downHits)
            {
                // Have we hit an adjacent block of the same colour
                if (hit.transform.tag == transform.tag)
                {
                    retBlocks.Add(hit.transform.GetComponent<DestructibleBlock>());
                    break;
                }
            }

            // Test for blocks to the left of us
            foreach (RaycastHit hit in leftHits)
            {
                // Have we hit an adjacent block of the same colour
                if (hit.transform.tag == transform.tag)
                {
                    retBlocks.Add(hit.transform.GetComponent<DestructibleBlock>());
                    break;
                }
            }

            // Test for for blocks to the right
            foreach (RaycastHit hit in rightHits)
            {
                // Have we hit an adjacent block of the same colour
                if (hit.transform.tag == transform.tag)
                {
                    retBlocks.Add(hit.transform.GetComponent<DestructibleBlock>());
                    break;
                }
            }
            return retBlocks;
        }

        //--------------------------------------------------------
        /// <summary>
        /// Finds and destroys any adjacent blocks of the same type/colour
        /// </summary>
        void DestroyAdjacentBlocks()
        {
            IList<DestructibleBlock> adjacentBlocks = FindAdjacentBlocks();
            HideAndDestroyBlock();

            foreach (DestructibleBlock block in adjacentBlocks)
            {
                block.DestroyAdjacentBlocks();
            }
        }

        //--------------------------------------------------------
        /// <summary>
        /// Hides our block transform before destroying it.  This is so other adjacent blocks don't find
        /// us while we are in the process of being destroyed
        /// </summary>
        void HideAndDestroyBlock()
        {
            gameObject.SetActive(false);
            Destroy(gameObject);
        }

        //--------------------------------------------------------
        /// <summary>
        /// Instantiates a POP effect when we successfully destroy a group of blocks
        /// </summary>
        void CreatePopEffect()
        {
            Instantiate(_popPrefab, transform.position, transform.rotation);
        }
        
        //--------------------------------------------------------
        /// <summary>
        /// Returns true if the rigidybody is moving, false otherwise
        /// </summary>
        public bool IsMoving
        {
            get
            {
                return !GetComponent<Rigidbody>().IsSleeping();
            }
        }
    }
}

#if NO_AND_ERROR
public void TEXT1() 
{
	int textNum = 1;
	if (textNum == 1) 
	{
		textNum = 2;
    }
}
public void TEXT2()
{
    int textNum = 1;
    if (textNum == 1)
    {
        textNum = 2;
    }
}
public void TEXT3()
{
    int textNum = 1;
    if (textNum == 1)
    {
        textNum = 2;
    }
}

public void TEXT4()
{
    int textNum = 1;
    if (textNum == 1)
    {
        textNum = 2;
    }
}

public void TEXT5()
{
    int textNum = 1;
    if (textNum == 1)
    {
        textNum = 2;
    }
}

public void TEXT6()
{
    int textNum = 1;
    if (textNum == 1)
    {
        textNum = 2;
    }
}

public void TEXT8()
{
    int textNum = 1;
    if (textNum == 1)
    {
        textNum = 2;
    }
}

public void TEXT9()
{
    int textNum = 1;
    if (textNum == 1)
    {
        textNum = 2;
    }
}

public void TEXT10()
{
    int textNum = 1;
    if (textNum == 1)
    {
        textNum = 2;
    }
}

public void TEXT11()
{
    int textNum = 1;
    if (textNum == 1)
    {
        textNum = 2;
    }
}

public void TEXT12()
{
    int textNum = 1;
    if (textNum == 1)
    {
        textNum = 2;
    }
}

public void TEXT13()
{
    int textNum = 1;
    if (textNum == 1)
    {
        textNum = 2;
    }
}

public void TEXT14()
{
    int textNum = 1;
    if (textNum == 1)
    {
        textNum = 2;
    }
}

public void TEXT15()
{
    int textNum = 1;
    if (textNum == 1)
    {
        textNum = 2;
    }
}

public void TEXT16()
{
    int textNum = 1;
    if (textNum == 1)
    {
        textNum = 2;
    }
}

public void TEXT17()
{
    int textNum = 1;
    if (textNum == 1)
    {
        textNum = 2;
    }
}
#endif
